package com.dizner.usbt;

import android.app.Activity;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.hardware.usb.UsbManager;
import android.os.Handler;
import android.util.Log;

import androidx.lifecycle.Lifecycle;
import androidx.lifecycle.LifecycleObserver;
import androidx.lifecycle.OnLifecycleEvent;

import com.github.mjdev.libaums.UsbMassStorageDevice;
import com.github.mjdev.libaums.fs.FileSystem;
import com.github.mjdev.libaums.fs.UsbFile;
import com.github.mjdev.libaums.fs.UsbFileStreamFactory;
import com.github.mjdev.libaums.partition.Partition;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.OutputStream;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Locale;

public class USBStoreyManager implements LifecycleObserver {
    private static final String TAG = "MediaReceiver";

    private static final String ACTION_USB_PERMISSION = "com.dizner.usbt.USB_PERMISSION";
    private UsbManager mUsbManager;
    private PendingIntent mPermissionIntent;
    private static Activity mContext;

    private MediaReceiver mUsbReceiver;

    private static final String EXPORT_FILE_NAME = "导出文件";

    private static final String EXPORT_FILE_TIME_PATTERN = "yyyy-MM-dd_HH_mm_ss_sss";

    private SimpleDateFormat dateFormat;

    private OnUSEStatusChangeListener mStatusChangeListener;


    private static Handler mHandler = new Handler();


    public static USBStoreyManager getInstance(Activity context) {
        mContext = context;

        return Build.INSTANCE;
    }

    private USBStoreyManager() {

        init();
    }

    private static class Build {
        static final USBStoreyManager INSTANCE = new USBStoreyManager();
    }

    private void init() {
        mPermissionIntent = PendingIntent.getBroadcast(mContext, 0, new Intent(ACTION_USB_PERMISSION), 0);
        mUsbReceiver = new MediaReceiver();
        dateFormat = new SimpleDateFormat(EXPORT_FILE_TIME_PATTERN, Locale.CHINA);
        mUsbManager = (UsbManager) mContext.getSystemService(Context.USB_SERVICE);

        IntentFilter intentFilter = new IntentFilter();
        intentFilter.addAction(UsbManager.ACTION_USB_DEVICE_ATTACHED);
        intentFilter.addAction(UsbManager.ACTION_USB_DEVICE_DETACHED);
        intentFilter.addAction(ACTION_USB_PERMISSION);
        mContext.registerReceiver(mUsbReceiver, intentFilter);

    }

    public void setStatusChangeListener(OnUSEStatusChangeListener statusChangeListener) {
        this.mStatusChangeListener = statusChangeListener;

//        UsbMassStorageDevice[] storageDevices = UsbMassStorageDevice.getMassStorageDevices(mContext);
//        if (storageDevices.length > 0) {
//            if (mStatusChangeListener != null) {
//                mStatusChangeListener.onAttached();
//            }
//        } else {
//            if (mStatusChangeListener != null) {
//                mStatusChangeListener.onExportError("无可用设备");
//            }
//        }

        mHandler.postDelayed(new Runnable() {
            @Override
            public void run() {
                initDevice();
            }
        }, 4000);
    }

    private void logShow(String msg) {
        Log.i(TAG, "returnMsg" + msg);
    }

    private void initDevice() {
        try {
            UsbMassStorageDevice[] storageDevices = UsbMassStorageDevice.getMassStorageDevices(mContext);
            if (storageDevices.length > 0) {
                // 获取分区
                UsbMassStorageDevice storageDevice = storageDevices[0];
                // 初始化
                if (!mUsbManager.hasPermission(storageDevice.getUsbDevice())) {
                    mUsbManager.requestPermission(storageDevice.getUsbDevice(), mPermissionIntent);
                    mHandler.postDelayed(new Runnable() {
                        @Override
                        public void run() {
                            initDevice();
                        }
                    }, 500);
                    return;
                }
                try {
                    storageDevice.init();
                } catch (IOException e) {
                    if (mStatusChangeListener != null) {
                        mStatusChangeListener.onUSBError("初始化设备失败");
                        return;
                    }
                    e.printStackTrace();
                }

                List<Partition> partitions = storageDevice.getPartitions();
                if (partitions.size() == 0) {
                    logShow("错误: 读取分区失败");
                    if (mStatusChangeListener != null) {
                        mStatusChangeListener.onUSBError("读取分区失败,请重试");
                    }
                    return;
                }
                // 仅使用第一分区
                FileSystem fileSystem = partitions.get(0).getFileSystem();


                if (mStatusChangeListener != null) {
                    mStatusChangeListener.onReady(fileSystem.getVolumeLabel(), fileSystem.getCapacity(), fileSystem.getFreeSpace());
                }
            } else {
                if (mStatusChangeListener != null) {
                    mStatusChangeListener.onUSBError("无可用USB设备");
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void exportFile(File targetFile) {
        if (targetFile == null || !targetFile.canRead()) {
            if (mStatusChangeListener != null) {
                mStatusChangeListener.onExportError("文件不存在");
            }
            return;
        }
        UsbMassStorageDevice[] storageDevices = UsbMassStorageDevice.getMassStorageDevices(mContext);
        if (storageDevices.length > 0) {
            copyFileToUSB(storageDevices[0], targetFile);
        }
    }

    private void copyFileToUSB(UsbMassStorageDevice storageDevice, File targetFile) {
        // 申请USB权限
        if (!mUsbManager.hasPermission(storageDevice.getUsbDevice())) {
            mUsbManager.requestPermission(storageDevice.getUsbDevice(), mPermissionIntent);
            logShow("错误: 等待授权");
            if (mStatusChangeListener != null) {
                mStatusChangeListener.onUSBError("请重试");
            }
            return;
        }
        // 初始化
        try {
            storageDevice.init();
        } catch (IOException e) {
            if (mStatusChangeListener != null) {
                mStatusChangeListener.onUSBError("初始化设备失败");
                return;
            }
            e.printStackTrace();
        }
        // 获取分区
        List<Partition> partitions = storageDevice.getPartitions();
        if (partitions.size() == 0) {
            logShow("错误: 读取分区失败");
            if (mStatusChangeListener != null) {
                mStatusChangeListener.onExportError("读取分区失败,请重试");
            }
            return;
        }
        // 仅使用第一分区
        FileSystem fileSystem = partitions.get(0).getFileSystem();

        if (fileSystem.getFreeSpace() < targetFile.length()) {
            if (mStatusChangeListener != null) {
                mStatusChangeListener.onExportError("目标设备空间不足");
                return;
            }
        }
        logShow("Volume Label: " + fileSystem.getVolumeLabel());
        logShow("Capacity: " + fSize(fileSystem.getCapacity()));
        logShow("Occupied Space: " + fSize(fileSystem.getOccupiedSpace()));
        logShow("Free Space: " + fSize(fileSystem.getFreeSpace()));
        logShow("Chunk size: " + fSize(fileSystem.getChunkSize()));

        UsbFile root = fileSystem.getRootDirectory();
//        UsbFile[] files = root.listFiles();
//        logShow("当前有: " + files.length + "个文件");
//                for (UsbFile file : files) {
//                    logShow("文件: " + file.getName());
//                }

        // 新建文件
        UsbFile newFile = null;
        try {
            newFile = root.createFile(String.format("%s-%s%s", EXPORT_FILE_NAME, dateFormat.format(new Date()), ".csv"));
        } catch (IOException e) {
            e.printStackTrace();
            if (mStatusChangeListener != null) {
                mStatusChangeListener.onExportError("创建文件失败");
                return;
            }
            return;
        }
        logShow("新建文件: " + newFile.getName());


        if (mStatusChangeListener != null) {
            mStatusChangeListener.onExportStart();
        }

        // 写文件
        // OutputStream os = new UsbFileOutputStream(newFile);
        OutputStream os = UsbFileStreamFactory.createBufferedOutputStream(newFile, fileSystem);

        FileInputStream inputStream = null;
        try {
            inputStream = new FileInputStream(targetFile);

            byte[] buf = new byte[1024];
            int length = 0;
            //循环读取文件内容，输入流中将最多buf.length个字节的数据读入一个buf数组中,返回类型是读取到的字节数。
            //当文件读取到结尾时返回 -1,循环结束。
            while ((length = inputStream.read(buf)) != -1) {
                os.write(buf, 0, length);
            }
            inputStream.close();
            os.close();
            logShow("写文件: " + newFile.getName());
        } catch (FileNotFoundException e) {
            if (mStatusChangeListener != null) {
                mStatusChangeListener.onExportError("目标文件读取失败");
                return;
            }
        } catch (IOException e) {
            if (mStatusChangeListener != null) {
                mStatusChangeListener.onExportError("写入文件失败");
                return;
            }
        }


        // 读文件
        // InputStream is = new UsbFileInputStream(newFile);
//                InputStream is = UsbFileStreamFactory.createBufferedInputStream(newFile, fileSystem);
//                byte[] buffer = new byte[fileSystem.getChunkSize()];
//                int len;
//                File sdFile = new File("/sdcard/111");
//                sdFile.mkdirs();
//                FileOutputStream sdOut = new FileOutputStream(sdFile.getAbsolutePath() + "/" + newFile.getName());
//                while ((len = is.read(buffer)) != -1) {
//                    sdOut.write(buffer, 0, len);
//                }
//                is.close();
//                sdOut.close();
//                logShow("读文件: " + newFile.getName() + " ->复制到/sdcard/111/");

        storageDevice.close();

        if (mStatusChangeListener != null) {
            mStatusChangeListener.onExportCompleted();
        }
    }

    public static String fSize(long sizeInByte) {
        if (sizeInByte < 1024)
            return String.format("%s", sizeInByte);
        else if (sizeInByte < 1024 * 1024)
            return String.format(Locale.CANADA, "%.2fKB", sizeInByte / 1024.);
        else if (sizeInByte < 1024 * 1024 * 1024)
            return String.format(Locale.CANADA, "%.2fMB", sizeInByte / 1024. / 1024);
        else
            return String.format(Locale.CANADA, "%.2fGB", sizeInByte / 1024. / 1024 / 1024);
    }

    @OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
    protected void onDestroy() {
        mContext.unregisterReceiver(mUsbReceiver);
        mContext = null;
    }


    interface OnUSEStatusChangeListener {
        /*usb插入*/
        void onAttached();

        /*usb断开*/
        void onDetached();

        /*准备就绪*/
        void onReady(String volumeLabel, long capacity, long freeSpace);

        /*导出开始*/
        void onExportStart();

        /*导出完成*/
        void onExportCompleted();

        /*导出错误*/
        void onExportError(String message);

        /*USB错误*/
        void onUSBError(String message);
    }

    class MediaReceiver extends BroadcastReceiver {

        public void onReceive(Context context, Intent intent) {
            Log.d(TAG, "onReceive: " + intent);
            String action = intent.getAction();
            if (action == null)
                return;
            switch (action) {
                case ACTION_USB_PERMISSION://用户授权广播
//                    synchronized (this) {
//                        if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)) { //允许权限申请
//                            logShow("用户授权，开始访问USB设备");
//                            test();
//                        } else {
//                            logShow("用户未授权，访问USB设备失败");
//                        }
//                    }
                    mHandler.postDelayed(new Runnable() {
                        @Override
                        public void run() {
                            initDevice();
                        }
                    }, 500);
                    break;
                case UsbManager.ACTION_USB_DEVICE_ATTACHED://USB设备插入广播
                    logShow("USB设备插入");
                    if (mStatusChangeListener != null) {
                        mStatusChangeListener.onAttached();
                    }
                    mHandler.postDelayed(new Runnable() {
                        @Override
                        public void run() {
                            initDevice();
                        }
                    }, 500);
                    break;
                case UsbManager.ACTION_USB_DEVICE_DETACHED://USB设备拔出广播
                    logShow("USB设备拔出");
                    if (mStatusChangeListener != null) {
                        mStatusChangeListener.onDetached();
                    }
                    break;
            }
        }
    }
}
